#pragma once
#include "..\DXAMLCommon.h"
#include "Base.h"
#include "InputSource.h"
#include "CharacterSource.h"
#include "_stack.h"
#include "Position.h"


class Scanner :
	public Base
{
private: 
	Scanner(const Scanner &);
public: 
	Scanner(struct IMalloc * pMalloc);
	virtual ~Scanner();
	void Initialize();
	void Reset();
	void PushInputSource(InputSource * pInputSource, struct IMultiLanguage2 * pMultiLanguage);
	InputSource * PopInputSource();
private: 
	void SetEncoding(struct StringPtr * pEncoding, bool fLittleEndian, struct IMultiLanguage2 * pMultiLaguage, bool fDetectedByStream);
public: 
	void SetEncoding(struct StringPtr *, struct IMultiLanguage2 *);
	void SetNamespaces(bool);
	void SetRandomAccess(bool);
	unsigned long GetColumnNumber();
	unsigned long GetLineNumber();
	XINT32 GetToken();
	XINT32 GetTokenDeclInner();
	XINT32 GetTokenType();
	void ReportSameTokenAgain();
	XINT32 GetTokenSize();
	void GetTokenValue(struct StringPtr *);
	void GetTokenValueQName(struct StringPtr *, struct StringPtr *);
	void DiscardToken();
	void GetExtendedPosition(struct Position *);
	void SetExtendedPosition(struct Position *);
	void SetInXmlDecl(bool);
	struct Position * GetAttributeValuePosition();
	wchar_t GetAttributeQuote();
	void RescanAttributeValue(struct Position *, wchar_t);
	void SetChunkSize(XINT32);
	bool ChunkIsFull();
	bool MoreDataAvailable();
	class AutodetectInput :
		public Base
	{
	public: 
		AutodetectInput(struct IMalloc *);
		void Initialize(InputSource *);
		void Delete();
		void PassBufferToCharacterSource(CharacterSource * pCharacterSource);
		void TakeBufferFromCharacterSource(CharacterSource *);
		XUINT8 GetByte();
		XINT32 IsEndOfInput();
		void SetSegment();
		void ResetFromStart();
	private: 
		XUINT8 * _pbInput;
		unsigned long _cbInput;
		XUINT8 * _pbCurr;
		XUINT8 * _pbSeg;
		XUINT8 * _pbEnd;
		XINT32 _fEndOfInput;
		InputSource * _pInputSource;
	};
private: 
	void operator=(const Scanner &);
		 //void(none)(* function)() *
	void PushCharacterSource(InputSource * pInputSource, struct IMultiLanguage2 * pMultiLanguage);
	bool DetectEncodingFromBOM(Scanner::AutodetectInput * pInput, XUINT32 * pnCodePage, bool * pfLittleEndian);
	bool DetectEncodingFromFirstCharacter(Scanner::AutodetectInput * pInput, XUINT32 * pnCodePage, bool * pfLittleEndian);
	bool CreateAndVerifyCharacterSource(InputSource * pInputSource, Scanner::AutodetectInput * pInput, struct StringPtr * pstrEncodingName, XUINT32 nCodePage, struct IMultiLanguage2 * pMultiLanguage);
	void CheckCheck();
	void CheckEndOfInput();
	void CheckPsi();
	void CheckOmega();
	void CheckWhitespace();
	void ScanAnd();
	void ScanAttribute();
	void ScanAttributeEqual();
	void ScanAttributeValue();
	void ScanCarriageReturn();
	bool ScanCrNl();
	void ScanCdSect();
	void ScanCdSectData();
	void ScanCdSectEnd();
	void ScanCharRef();
	void ScanComment();
	void ScanCommentData();
	void ScanCommentEnd();
	void ScanCondSect();
	void ScanCondSect1();
	void ScanCondSect2();
	void ScanContent();
	void ScanContentPcData();
	void ScanDeclAttlist();
	void ScanDeclAttlist1();
	void ScanDeclAttlist2();
	void ScanDeclAttlist3();
	void ScanDeclAttlist4();
	void ScanDeclAttlist5();
	void ScanDeclAttlist6();
	void ScanDeclAttlist7();
	void ScanDeclDoctype();
	void ScanDeclDoctype1();
	void ScanDeclDoctype2();
	void ScanDeclDoctype3();
	void ScanDeclDoctype4();
	void ScanDeclElement();
	void ScanDeclElement1();
	void ScanDeclElement2();
	void ScanDeclElement3();
	void ScanDeclEnd();
	void ScanDeclEntity();
	void ScanDeclEntity1();
	void ScanDeclEntity2();
	void ScanDeclEntity3();
	void ScanDeclName();
	void ScanDeclNameQualified();
	void ScanDeclNotation();
	void ScanDeclNotation1();
	void ScanDeclNotation2();
	void ScanETag();
	void ScanEntityValue();
	void ScanExclamation();
	void ScanExclamationSubset();
	void ScanIgnoreSect();
	void ScanLessThan();
	void ScanLessThanProlog();
	void ScanLessThanSubset();
	void ScanLiteral();
	void ScanLiteralValue();
	void ScanNameQualifiedN();
	void ScanNameN();
	void ScanNameNN();
	void ScanNdataDecl();
	void ScanNmtoken();
	void ScanPercentSubset();
	void ScanPercentEntityValue();
	void ScanPi();
	void ScanPiData();
	void ScanPiEnd();
	void ScanPiWhitespace();
	void ScanProlog();
	void ScanPublicId();
	void ScanQuoteEnd();
	void ScanRightBracketSubset();
	void ScanSameTokenAgain();
	void ScanSpace();
	void ScanSubset();
	void ScanSystemId();
	void ScanXmlDecl();
	void ScanXmlDeclAttribute();
	void ProcessChunkOverflow();
	_stack<CharacterSource *,2> _characterSources;

	CharacterSource * _pCharacterSource;
	XINT32 _nToken;
	_stack<void (__thiscall Scanner::*)(void),8> _scanContexts;

	//void(none)(* function)() * _pfnScan;
	//void(none)(* function)() * _pfnScanNext;
	wchar_t _whLookahead;
	_stack<unsigned short,2> _entityValueQuotes;

	struct Position _posAttValue;

	wchar_t _whQuote;
	XINT32 _nSize;
	XINT32 _nState;
	bool _fNamespaces;
	bool _fRandomAccess;
	XINT32 _nNsPrefix;
	//void(none)(* function)() * _pfnScanName;
	//void(none)(* function)() * _pfnScanNameQualified;
	Scanner::AutodetectInput _AutodetectInput;
	void ResetSegment();
	void SetSegmentDelta(HRESULT);
	void SetLine(unsigned long);
	wchar_t GetCharacter();
	void SetSegment();
	XINT32 GetSegmentSize();
	void SavePosition();
	void RestorePosition();
	bool GetEndOfInput();
	bool GetCharacterIfEqual(char);
	void FixAsciiCharacter(char);
	void Scan();
	void ScanName();
	void ScanNameQualified();

};